package com.yuandian.management.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuandian.api.management.entity.ConfMpAbility;
import com.yuandian.api.management.po.ConfMpAbilityInfo;
import com.yuandian.api.management.po.ConfMpAbilityParams;
import com.yuandian.api.management.vo.ConfMpAll;
import com.yuandian.api.management.vo.OptionVo;
import com.yuandian.bpm.common.core.util.R;
import com.yuandian.management.mapper.ConfMpAbilityMapper;
import com.yuandian.management.mapper.ConfMpServiceMapper;
import com.yuandian.management.service.ConfMpAbilityService;
import com.yuandian.management.service.ConfMpServiceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 中台监控-能力配置表-Service实现
 * @author zfsn
 * @date 2023-4-18
 */
@Service
public class ConfMpAbilityServiceImpl extends ServiceImpl<ConfMpAbilityMapper, ConfMpAbility>
		implements ConfMpAbilityService {

	@Autowired
	private ConfMpAbilityMapper confMpAbilityMapper;

	@Autowired
	private ConfMpServiceService confMpServiceService;

	/**
	 * 根据能力编码获取一条能力配置数据
	 * @param abilityCode 能力编码
	 * @return 能力配置实体
	 */
	private ConfMpAbility getByAbilityCode(String abilityCode) {
		return lambdaQuery().eq(ConfMpAbility::getAbilityCode, abilityCode).one();
	}

	/**
	 * 分页查询
	 * @param params 中台监控-能力配置请求参数
	 * @return 通用返回对象
	 */
	@Override
	public R<Page<ConfMpAbility>> page(ConfMpAbilityParams params) {
		Page<ConfMpAbility> page = Page.of(params.getCurrent(), params.getSize());
		page.addOrder(params.orders()).orders().forEach(orderItem -> orderItem.setColumn(StrUtil.toUnderlineCase(orderItem.getColumn())));
		Page<ConfMpAbility> pages = lambdaQuery()
				.eq(params.getSystemId() != null, ConfMpAbility::getSystemId, params.getSystemId())
				.eq(StrUtil.isNotEmpty(params.getOrgCode()), ConfMpAbility::getOrgCode, params.getOrgCode())
				.like(StrUtil.isNotEmpty(params.getAbilityCode()), ConfMpAbility::getAbilityCode, params.getAbilityCode())
				.like(StrUtil.isNotEmpty(params.getAbilityName()), ConfMpAbility::getAbilityName, params.getAbilityName()).page(page);
		return R.ok(pages);
	}

	/**
	 * 新增数据
	 * @param params 中台监控-能力配置请求参数
	 * @return 通用返回对象
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public R<Boolean> saveWrap(ConfMpAbilityParams params) {
		// 1、校验能力编码唯一性
		if (ObjectUtil.isNotNull(getByAbilityCode(params.getAbilityCode()))) {
			return R.failed("新增失败，已存在相同的能力编码！");
		}
        // 2、切分能力所属的中台和单位
		String abilityCode = params.getAbilityCode();
        // 能力编码中，所属中台：第二位    单位：第3位~第5位
		params.setMiddlePlatformId(abilityCode.substring(1, 2));;
		params.setOrgCode(abilityCode.substring(2, 5));
		// 3、新增能力配置
		ConfMpAbility confMpAbility = BeanUtil.copyProperties(params, ConfMpAbility.class);
		save(confMpAbility);
		return R.ok(Boolean.TRUE, "新增成功");
	}

	/**
	 * 通过主键更新数据
	 * @param params 中台监控-能力配置请求参数
	 * @return 通用返回对象
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public R<Boolean> updateByIdWrap(ConfMpAbilityParams params) {
		// 1、校验请求参数
		Integer abilityId = params.getId();
		if (abilityId == null) {
			return R.failed("更新失败，能力id不能为空！");
		}
		// 2、通过id获取能力配置
		ConfMpAbility abilityById = getById(abilityId);
		// 3、校验该配置是否存在
		if (ObjectUtil.isNull(abilityById)) {
			return R.failed("更新失败，不存在该能力配置！");
		}
		/*
		 * 4、校验能力编码的唯一性
		 * 通过能力编码获取能力配置如果为空，说明不存在相同的能力编码，
		 * 或者不为空，但id和要修改的能力配置的id一样，说明修改的是自己的能力编码，这也是唯一的，
		 * 所以这里的判断条件是：当通过能力编码获取能力配置不为空且id不一致时，认为存在相同的能力编码
		 */
		ConfMpAbility abilityByCode = getByAbilityCode(params.getAbilityCode());
		if (ObjectUtil.isNotNull(abilityByCode) && !abilityId.equals(abilityByCode.getId())) {
			return R.failed("更新失败，已存在相同的能力编码！");
		}
		// 5、切分能力所属的中台和单位
		String abilityCode = params.getAbilityCode();
		// 能力编码中，所属中台：第二位    单位：第3位~第5位
		params.setMiddlePlatformId(abilityCode.substring(1, 2));;
		params.setOrgCode(abilityCode.substring(2, 5));
		// 6、更新能力配置
		BeanUtil.copyProperties(params, abilityById);
		updateById(abilityById);
		return R.ok(Boolean.TRUE, "更新成功");
	}

	/**
	 * 通过主键删除数据
	 * @param idList 主键集合
	 * @return 通用返回对象
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public R<Boolean> removeByIdsWrap(List<Integer> idList) {
		// 1、校验请求参数
		if (CollUtil.isEmpty(idList)) {
			return R.failed("删除失败，主键集合不能为空");
		}
		// 2、根据能力id集合删除能力下的所有服务配置
		confMpServiceService.removeByAbilityIds(idList);
		// 3、删除能力配置
		removeByIds(idList);
		return R.ok(Boolean.TRUE, "删除成功");
	}

	/**
	 * 查询移动中台监控配置信息大全
	 * @param params 中台监控-能力配置请求参数
	 * @return 通用返回对象
	 */
	@Override
	public R<ConfMpAll> infoAll(ConfMpAbilityParams params) {
		ConfMpAll confMpAll = new ConfMpAll();
		List<ConfMpAbilityInfo> abilityInfoList = confMpAbilityMapper.queryConfMpAll();
		confMpAll.setAbilityInfoList(abilityInfoList);
		return R.ok(confMpAll);
	}

	/**
	 * 查询能力选项
	 * @return 通用返回对象
	 */
	@Override
	public R<List<OptionVo>> option() {
		List<ConfMpAbility> abilityList = lambdaQuery().select(
				ConfMpAbility::getId, ConfMpAbility::getAbilityCode, ConfMpAbility::getAbilityName).list();
		List<OptionVo> list = new ArrayList<>();
		abilityList.forEach(ability -> {
			OptionVo vo = new OptionVo();
			vo.setLabel(ability.getAbilityName());
			vo.setValue(ability.getAbilityCode());
			vo.setId(ability.getId());
			list.add(vo);
		});
		return R.ok(list);
	}

	/**
	 * 查询单位编码及单位名称
	 * @return
	 */
	public R getOrg() {
		List<OptionVo> list = new ArrayList<>();
		Map<String, String> map = confMpServiceService.getOrg();
		if (map != null && map.size() > 0) {
			OptionVo optionVo = null;
			for (String key : map.keySet()){
				optionVo = new OptionVo();
				optionVo.setLabel(map.get(key));
				optionVo.setValue(key);
				list.add(optionVo);
			}
		}
		return R.ok(list);
	}
}